package pack1

import (
	"fmt"
	"math"
	"reflect"
	"time"
)

type Point struct {
	x, y float64
}

func (p *Point) Abs() float64 {
	return math.Sqrt(p.x*p.x + p.y*p.y)
}

type NamedPoint struct {
	name string
	Point
}

func (p *NamedPoint) Abs() float64 {
	return p.Point.Abs() * 100
}

type Engine interface {
	start()
	stop()
}
type Car struct {
	wheelCount int
	Engine
}

func (c *Car) numberOfWheels() int {
	return c.wheelCount
}

func (c *Car) start() {
	fmt.Println("car start")
}

func (c *Car) stop() {
	fmt.Println("car stop")
}

type Mercedes struct {
	Car
}

func (m *Mercedes) sayHiToMerkel() {
	fmt.Println("number of wheels: ", m.numberOfWheels())
	m.start()
	m.stop()
}

func TestInterite() {
	p1 := &Point{10, 10}
	fmt.Println("p1:", p1.Abs())

	p2 := &NamedPoint{"testPoint", Point{10,10}}
	fmt.Println("p2:", p2, p2.Abs())

	m := &Mercedes{Car{wheelCount: 10}}
	m.sayHiToMerkel()
}

type idBase struct {
	uuid string
}

type ThirdPartyConfig struct {
	name string
	idBase
}

type Student struct {
	username string "the student name string type"
	age      int    "the student age int type"
}

func (s *Student) add(ss Student) {
	s.age += ss.age
	s.username += ss.username
	//return ss
}

func NewConfig(uuid string, name string) ThirdPartyConfig {
	config := ThirdPartyConfig{name: name}
	config.uuid = uuid
	return config
}

type IntVector []int

func (a IntVector) Sum() (t int) {
	for _, x := range a {
		t += x
	}
	return
}

func (a *IntVector) append(s int) {
	*a = append(*a, s)
}

func (a IntVector) len() int {
	return len(a)
}

type Employee struct {
	salary float64
}

func (e *Employee) giveRaise(percentage float64) {
	raiseMoney := e.salary * percentage
	e.salary += raiseMoney
}

type myTime struct {
	time.Time
}

func (mt myTime) myfn() string {
	return mt.Time.String()[:3]
}

func TestNonStructCustomMethodForIntArr() {
	intV := IntVector{1, 2, 3}
	sum := intV.Sum()
	fmt.Println("sum:", sum)

	intV2 := make(IntVector, 10)
	intV2[0] = 1
	intV2[1] = 2
	sum2 := intV2.Sum()
	fmt.Println("sum2:", sum2, cap(intV2), len(intV2))
	intV2.append(3)
	intV2.append(4)
	fmt.Println("after append:", intV2, intV2.len(), intV2.Sum())

	e1 := Employee{salary: 10000.00}
	fmt.Println("before raise salary:", e1)
	e1.giveRaise(0.1)
	fmt.Println("after raise salary:", e1)

	mt1 := myTime{time.Now()}
	fmt.Println("myfn:", mt1.myfn(), mt1.String())
}

func InitStruct() {
	var stu Student
	stu.username = "byref"
	stu.age = 10

	stu2 := Student{"test", 1}

	stu.add(stu2)

	fmt.Println("stu:", stu)
	t := reflect.TypeOf(stu)
	f, _ := t.FieldByName("username")
	fmt.Println("field", f.Tag, "f.name:", f.Name, "f.type", f.Type)

	config := ThirdPartyConfig{name: "abc"}
	config.uuid = "uuid"

	config2 := new(ThirdPartyConfig)
	config2.uuid = "uuid2"
	config2.name = "dfg"

	fmt.Println(config, config2)
	//reflect.Value()
}
